package com.signway.javaui.component;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.TouchEvent;

public class ControlBar extends Component
        implements Component.DrawTask,
        Component.EstimateSizeListener,
        Component.TouchEventListener {

    public static final float CIRCLE_ANGLE = 360.0f;
    public static final int DEF_UNFILL_COLOR = 0xFF808080;
    public static final int DEF_FILL_COLOR = 0xFF1E90FF;

    /* 自定义XML属性 */
    public static final String ATTR_UNFILL_COLOR = "unfill_color";
    public static final String ATTR_FILL_COLOR = "fill_color";
    public static final String ATTR_CIRCLE_WIDTH = "circle_width";
    public static final String ATTR_COUNT = "max";
    public static final String ATTR_CURRENT_COUNT = "progress";
    public static final String ATTR_SPLIT_SIZE = "split_size";/*  */
    public static final String ATTR_CIRCLE_RADIUS = "circle_radius";
    public static final String ATTR_CENTER_PIXELMAP = "center_pixelmap";
    public static final String ATTR_CLOCKWISE_ROTATION = "clockwise_rotation";

    private int width;
    private int height;
    private Color unFillColor = new Color(DEF_UNFILL_COLOR);
    private Color fillColor = new Color(DEF_FILL_COLOR);
    private int circleWidth = 30;/* 进度条宽度 */
    private int max = 10;/* 进度最大值 */
    private int progress = 0;/* 当前进度 */
    private int splitSize = 10;/* 间隔角度 */
    private int radius = 0;/* 半径 */
    private boolean clockwiseRotation = true;/* 默认顺时针旋转 */
    private PixelMap image = null;
    private Point centerPoint;

    public int getMax() {
        return max;
    }

    public void setProgress(int progress) {
        if (this.progress != progress) {
            this.progress = progress;
            invalidate();
            if (listener != null) {
                listener.onProgressChangeListener(progress);
            }
        }
    }

    private final Paint paint = new Paint();
    private final RectFloat centerRectFloat = new RectFloat();

    private ProgressChangeListener listener;

    public void setListener(ProgressChangeListener listener) {
        this.listener = listener;
    }

    public ControlBar(Context context) {
        super(context);
    }

    public ControlBar(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initAttrSet(attrSet);
        setEstimateSizeListener(this);
        if (!isClickable()) setClickable(true);
        setTouchEventListener(this);
        addDrawTask(this);
        listener = null;
    }

    private void initAttrSet(AttrSet attrSet) {
        if (attrSet == null) return;
        if (attrSet.getAttr(ATTR_UNFILL_COLOR).isPresent()) {
            unFillColor = attrSet.getAttr(ATTR_UNFILL_COLOR).get().getColorValue();
        }
        if (attrSet.getAttr(ATTR_FILL_COLOR).isPresent()) {
            fillColor = attrSet.getAttr(ATTR_FILL_COLOR).get().getColorValue();
        }
        if (attrSet.getAttr(ATTR_CIRCLE_WIDTH).isPresent()) {
            circleWidth = attrSet.getAttr(ATTR_CIRCLE_WIDTH).get().getDimensionValue();
        }
        if (attrSet.getAttr(ATTR_COUNT).isPresent()) {
            max = attrSet.getAttr(ATTR_COUNT).get().getIntegerValue();
        }
        if (attrSet.getAttr(ATTR_CURRENT_COUNT).isPresent()) {
            progress = attrSet.getAttr(ATTR_CURRENT_COUNT).get().getIntegerValue();
        }
        if (attrSet.getAttr(ATTR_SPLIT_SIZE).isPresent()) {
            splitSize = attrSet.getAttr(ATTR_SPLIT_SIZE).get().getIntegerValue();
        }
        if (attrSet.getAttr(ATTR_CIRCLE_RADIUS).isPresent()) {
            radius = attrSet.getAttr(ATTR_CIRCLE_RADIUS).get().getDimensionValue();
        }
        if (attrSet.getAttr(ATTR_CLOCKWISE_ROTATION).isPresent()) {
            clockwiseRotation = attrSet.getAttr(ATTR_CLOCKWISE_ROTATION).get().getBoolValue();
        }
        if (attrSet.getAttr(ATTR_CENTER_PIXELMAP).isPresent()) {
            Element element = attrSet.getAttr(ATTR_CENTER_PIXELMAP).get().getElement();
            if (element instanceof PixelMapElement) {
                image = ((PixelMapElement)element).getPixelMap();
            }
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        paint.setAntiAlias(true);
        paint.setStrokeWidth(circleWidth);
        paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        paint.setStyle(Paint.Style.STROKE_STYLE);
        int min = Math.min(width, height);
        int maxRadius = (min >> 1) - (circleWidth >> 1);
        if (radius == 0 || radius > maxRadius) {
            radius = maxRadius;
        }
        centerPoint = new Point(width >> 1, height >> 1);
        if (image != null) {
            drawImage(canvas);
        }
        drawCount(canvas);
    }

    private void drawImage(Canvas canvas) {
        int inRadius = radius - (circleWidth >> 1);
        centerRectFloat.left = (float) (width / 2 - Math.sqrt(2) * inRadius);
        centerRectFloat.top = (float) (height / 2 - Math.sqrt(2) * inRadius);
        centerRectFloat.right = (float) (width / 2 + Math.sqrt(2) * inRadius);
        centerRectFloat.bottom = (float) (height / 2 + Math.sqrt(2) * inRadius);

        Size imageSize = image.getImageInfo().size;
        if (imageSize.width < Math.sqrt(2) * inRadius) {
            centerRectFloat.left = (width - imageSize.width * 1.0f) / 2;
            centerRectFloat.right = (width + imageSize.width * 1.0f) / 2;
            centerRectFloat.top = (height - imageSize.height * 1.0f) / 2;
            centerRectFloat.bottom = (height + imageSize.height * 1.0f) / 2;
        }
        canvas.drawPixelMapHolderRect(new PixelMapHolder(image), centerRectFloat, paint);
    }

    private void drawCount(Canvas canvas) {
        float itemSize = (CIRCLE_ANGLE - max * splitSize) / max;
        RectFloat oval = new RectFloat(centerPoint.getPointX() - radius, centerPoint.getPointY() - radius,
                centerPoint.getPointX() + radius, centerPoint.getPointY() + radius);
        paint.setColor(unFillColor);
        for (int i = 0; i < max; i++) {
            Arc arc = new Arc((i * (itemSize + splitSize)) - 90, itemSize, false);
            canvas.drawArc(oval, arc, paint);
        }
        paint.setColor(fillColor);

        if (clockwiseRotation) {
            for (int i = 0; i < progress; i++) {
                Arc arc = new Arc((i * (itemSize + splitSize)) - 90, itemSize, false);
                canvas.drawArc(oval, arc, paint);
            }
        } else {
            for (int i = max - 1; i >= max - progress; i--) {
                Arc arc = new Arc((i * (itemSize + splitSize)) - 90, itemSize, false);
                canvas.drawArc(oval, arc, paint);
            }
        }
    }

    @Override
    public boolean onEstimateSize(int w, int h) {
        int wMode = EstimateSpec.getMode(w);
        int hMode = EstimateSpec.getMode(h);

        int wConfig = 0;
        switch (wMode) {
            case EstimateSpec.UNCONSTRAINT:
            case EstimateSpec.PRECISE:
                width = EstimateSpec.getSize(w);
            case EstimateSpec.NOT_EXCEED:
                wConfig = EstimateSpec.getSizeWithMode(width, EstimateSpec.PRECISE);
                break;
        }

        int hConfig = 0;
        switch (hMode) {
            case EstimateSpec.UNCONSTRAINT:
            case EstimateSpec.PRECISE:
                height = EstimateSpec.getSize(h);
            case EstimateSpec.NOT_EXCEED:
                hConfig = EstimateSpec.getSizeWithMode(height, EstimateSpec.PRECISE);
                break;
        }
        setEstimatedSize(wConfig, hConfig);
        return true;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        return false;
    }

    public interface ProgressChangeListener {
        void onProgressChangeListener(int progress);
    }
}
